use std::f64::consts::PI;

/**
 @author 林海-team5-88
 @date 2021-03-27
 @description 参考文档：https://doc.rust-lang.org/std/primitive.u32.html
*/
// 引入红绿灯模块类
use homework_class4::traffic_light::TrafficLight;

fn main() {
    
    // 初始一个红灯状态
    println!("--------------- 开始题目1程序：");
    let mut light = TrafficLight::Red;
    for x in (0..6) {
        println!("当前处于|{}|状态，时长{}秒", light.name(), light.time());
        light = light.switch(); // 增加换灯功能，红->黄->绿 通过 switch() 方法可以切换到下一个交通信号灯的状态
    }

    println!("--------------- 开始题目2程序：");
    let list:[u32;4] = [6,2,3,4]; // 没问题的序列
    // let list:[u32;2] = [u32::MAX,1] ; // 会导致溢出（测试溢出情况可以放开这个注释）
    match sum_num(&list) {
        Some(x) => println!("序列的和是：{}", x), 
        None => println!("序列大小超出了u32的定义，程序溢出无法求和，和应小于 u32::MAX 的定义范围。"),
    }

    println!("--------------- 开始题目3程序：");
    // 定义一个三角形
    let triangle = MyTriangle {
        a: 10.0,
        h: 5.0,
    };
    print_sharp_area(triangle);
    // 定义一个正方形
    let rectangle = MyRectangle {
        height:20.0,
        width:30.0,
    };
    print_sharp_area(rectangle);

    // 定义一个圆
    let circle = MyCircle {
        r:5.0,
    };
    print_sharp_area(circle);

}

// 第一题解题函数，请看 traffic_light.rs 附加了红绿灯切换逻辑和单元测试，所以单独移出去了。

// 第二题解题函数
fn sum_num(list: &[u32]) -> Option<u32>{
    let mut sum:u32 = 0;
    for i in list.iter() {
        // 如果最大值减去当前的求和值，小于待相加的值就会导致溢出
        if &(u32::MAX - sum) < i {
            // 提前终止方法要加 return
            return None;
        }
        sum += i;
    }
    Some(sum)
}

// 第三题解题函数
fn print_sharp_area<T:Shape>(shape:T) {
    println!("当前图形是：{}, 面积是：{}", shape.name(), shape.count_area());
}


trait Shape {
    fn count_area(&self) -> f64 ;
    fn name(&self) -> String;
}

struct MyTriangle {
    a: f64, // 三角形的底
    h: f64, // 三角形的高
}

struct MyRectangle {
    width: f64,
    height: f64,
}

struct MyCircle {
    r: f64,
}


// trait方法实现
impl Shape for MyTriangle {
    fn count_area(&self) -> f64  {
        // 公式 S= a×h÷2 
        self.a * self.h
    }

    fn name(&self) -> String {
        "三角形".to_string()
    }
}

// trait方法实现
impl Shape for MyRectangle {
    fn count_area(&self) -> f64  {
        self.width * self.height
    }

    fn name(&self) -> String {
        "长方形".to_string()
    }
}

// trait方法实现
impl Shape for MyCircle {
    fn count_area(&self) -> f64  {
        self.r * self.r * PI // 3.14
    }

    fn name(&self) -> String {
        "圆形".to_string()
    }
}


